package com.caipos.actor.common.data;

import com.caipos.actor.common.data.id.DashboardId;
import com.caipos.actor.common.data.id.DeviceProfileId;
import com.caipos.actor.common.data.id.RuleChainId;
import com.caipos.actor.common.data.id.TenantId;
import com.caipos.ruleNode.profile.DeviceProfileData;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.*;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;
import java.io.IOException;

@Data
@ToString(exclude = {"image", "profileDataBytes"})
@EqualsAndHashCode(callSuper = true)
@Slf4j
public class DeviceProfile extends BaseData<DeviceProfileId> implements HasName, HasTenantId, HasRuleEngineProfile, ExportableEntity<DeviceProfileId>, HasImage, HasDefaultOption, HasVersion {

    private static final long serialVersionUID = 6998485460273302018L;

    private TenantId tenantId;
    private String name;
    private String description;
    private String image;
    private boolean isDefault;
    private DeviceProfileType type;
    private DeviceTransportType transportType;
    private DeviceProfileProvisionType provisionType;
    private RuleChainId defaultRuleChainId;
    private DashboardId defaultDashboardId;

    private String defaultQueueName;
    private transient DeviceProfileData profileData;
    @JsonIgnore
    @Getter
    @Setter
    private byte[] profileDataBytes;
    private String provisionDeviceKey;

    private RuleChainId defaultEdgeRuleChainId;

    private DeviceProfileId externalId;
    private Long version;

    public DeviceProfile() {
        super();
    }

    public DeviceProfile(DeviceProfileId deviceProfileId) {
        super(deviceProfileId);
    }

    public DeviceProfile(DeviceProfile deviceProfile) {
        super(deviceProfile);
        this.tenantId = deviceProfile.getTenantId();
        this.name = deviceProfile.getName();
        this.description = deviceProfile.getDescription();
        this.image = deviceProfile.getImage();
        this.isDefault = deviceProfile.isDefault();
        this.defaultRuleChainId = deviceProfile.getDefaultRuleChainId();
        this.defaultDashboardId = deviceProfile.getDefaultDashboardId();
        this.defaultQueueName = deviceProfile.getDefaultQueueName();
        this.setProfileData(deviceProfile.getProfileData());
        this.provisionDeviceKey = deviceProfile.getProvisionDeviceKey();
        this.defaultEdgeRuleChainId = deviceProfile.getDefaultEdgeRuleChainId();
        this.externalId = deviceProfile.getExternalId();
        this.version = deviceProfile.getVersion();
    }

    @Override
    public DeviceProfileId getId() {
        return super.getId();
    }

    @Override
    public long getCreatedTime() {
        return super.getCreatedTime();
    }

    public boolean isDefault() {
        return isDefault;
    }

    public DeviceProfileData getProfileData() {
        if (profileData != null) {
            return profileData;
        } else {
            if (profileDataBytes != null) {
                try {
                    profileData = mapper.readValue(new ByteArrayInputStream(profileDataBytes), DeviceProfileData.class);
                } catch (IOException e) {
                    log.warn("Can't deserialize device profile data: ", e);
                    return null;
                }
                return profileData;
            } else {
                return null;
            }
        }
    }

    public void setProfileData(DeviceProfileData data) {
        this.profileData = data;
        try {
            this.profileDataBytes = data != null ? mapper.writeValueAsBytes(data) : null;
        } catch (JsonProcessingException e) {
            log.warn("Can't serialize device profile data: ", e);
        }
    }

}
